import { Toast } from "antd-mobile";

/**
 * 地理定位工具类
 */
export class GeoWatcher {
  constructor(options = {}) {
    this.validateOptions(options);
    const {
      onUpdate,
      onError,
      enableHighAccuracy = true,
      timeout = 10000,
      maximumAge = 0,
    } = options;

    this.onUpdate = this.createCallback(onUpdate);
    this.onError = this.createCallback(onError);
    this.options = { enableHighAccuracy, timeout, maximumAge };
    this.watchId = null;
    this.isDestroyed = false;
  }

  /**
   * 检查地理定位支持和权限状态
   * @returns {Promise<Object|null>} 检查结果
   */
  static async check() {
    const geolocationSupport = this.checkGeolocationSupport();

    if (!geolocationSupport.supported) {
      this.showToast("当前环境不支持地理定位");
      return null;
    }

    const permissionStatus = await this.checkPermissionStatus();

    if (permissionStatus === "denied") {
      this.showToast("定位权限被拒绝，请在设置中开启");
      return null;
    }

    return {
      supported: geolocationSupport.supported,
      permission: permissionStatus,
    };
  }

  static checkGeolocationSupport() {
    const isSupported =
      typeof navigator !== "undefined" && "geolocation" in navigator;

    return {
      supported: isSupported,
      api: navigator?.geolocation || null,
    };
  }

  static async checkPermissionStatus() {
    try {
      if (navigator.permissions && navigator.permissions.query) {
        const result = await navigator.permissions.query({
          name: "geolocation",
        });
        return result.state;
      }
    } catch (error) {
      console.warn("检查权限状态失败:", error);
    }
    return "unknown";
  }

  static showToast(message) {
    Toast.show({
      content: message,
      position: "center",
      maskClickable: false,
    });
  }

  validateOptions(options) {
    if (typeof options !== "object" || options === null) {
      throw new Error("options 必须是一个对象");
    }
  }

  createCallback(callback) {
    return typeof callback === "function" ? callback : () => {};
  }

  ensureGeolocationSupport() {
    if (!("geolocation" in navigator)) {
      const error = new Error("当前环境不支持地理定位");
      this.handleError(error);
      throw error;
    }
  }

  handleError(error) {
    if (this.onError) {
      try {
        this.onError(error);
      } catch (callbackError) {
        console.error("错误回调执行失败:", callbackError);
      }
    }
  }

  /**
   * 开始监听地理位置变化
   * @returns {number|null} 监听ID
   */
  start() {
    if (this.isDestroyed) {
      console.warn("GeoWatcher 已被销毁，无法启动监听");
      return null;
    }

    if (this.watchId !== null) {
      console.warn("已在监听中，无需重复启动");
      return this.watchId;
    }

    try {
      this.ensureGeolocationSupport();

      this.watchId = navigator.geolocation.watchPosition(
        this.handlePositionUpdate.bind(this),
        this.handlePositionError.bind(this),
        this.options
      );

      return this.watchId;
    } catch (error) {
      this.handleError(error);
      return null;
    }
  }

  /**
   * 停止监听地理位置变化
   */
  stop() {
    if (this.watchId !== null && navigator.geolocation) {
      try {
        navigator.geolocation.clearWatch(this.watchId);
      } catch (error) {
        console.warn("停止监听失败:", error);
      }
      this.watchId = null;
    }
  }

  /**
   * 获取当前位置（单次定位）
   * @returns {Promise<GeolocationPosition>} 位置信息
   */
  async getPosition() {
    if (this.isDestroyed) {
      throw new Error("GeoWatcher 已被销毁");
    }

    this.ensureGeolocationSupport();

    return new Promise((resolve, reject) => {
      let isCompleted = false;

      const cleanup = (watchId, timeoutId) => {
        try {
          if (watchId !== null && navigator.geolocation) {
            navigator.geolocation.clearWatch(watchId);
          }
        } catch (error) {
          console.warn("清理监听失败:", error);
        }

        if (timeoutId) {
          clearTimeout(timeoutId);
        }
      };

      const timeoutId = this.options.timeout
        ? setTimeout(() => {
            if (isCompleted) return;

            isCompleted = true;
            const error = new Error("定位超时");
            this.handleError(error);
            reject(error);
          }, this.options.timeout)
        : null;

      const watchId = navigator.geolocation.watchPosition(
        (position) => {
          if (isCompleted) return;

          isCompleted = true;
          cleanup(watchId, timeoutId);

          if (this.onUpdate) {
            try {
              this.onUpdate(position);
            } catch (error) {
              console.error("位置更新回调执行失败:", error);
            }
          }

          resolve(position);
        },
        (error) => {
          if (isCompleted) return;

          isCompleted = true;
          cleanup(watchId, timeoutId);
          this.handleError(error);
          reject(error);
        },
        this.options
      );
    });
  }

  handlePositionUpdate(position) {
    if (this.onUpdate) {
      try {
        this.onUpdate(position);
      } catch (error) {
        console.error("位置更新回调执行失败:", error);
      }
    }
  }

  handlePositionError(error) {
    this.handleError(error);
  }

  /**
   * 销毁实例，清理资源
   */
  destroy() {
    this.stop();
    this.onUpdate = null;
    this.onError = null;
    this.isDestroyed = true;
  }

  /**
   * 获取当前监听状态
   * @returns {boolean} 是否正在监听
   */
  isWatching() {
    return this.watchId !== null;
  }
}

/**
 * 数字格式化工具类
 */
export class NumberFormatter {
  static formatNumberGroup(input, groupSize = 4, separator = " ") {
    // 参数验证
    if (input === null || input === undefined) {
      return "";
    }

    // 转换为字符串并移除所有非数字字符
    const cleanInput = String(input).replace(/\D/g, "");

    if (!cleanInput) {
      return "";
    }

    // 从右往左分组
    const groups = [];
    for (let i = cleanInput.length; i > 0; i -= groupSize) {
      const start = Math.max(0, i - groupSize);
      groups.unshift(cleanInput.slice(start, i));
    }

    return groups.join(separator);
  }

  static formatCardNumber(cardNumber) {
    return this.formatNumberGroup(cardNumber, 4, " ");
  }

  static formatPhoneNumber(phoneNumber) {
    const cleanPhone = String(phoneNumber).replace(/\D/g, "");

    if (cleanPhone.length === 11) {
      return `${cleanPhone.slice(0, 3)} ${cleanPhone.slice(
        3,
        7
      )} ${cleanPhone.slice(7)}`;
    }

    return cleanPhone;
  }

  static formatIdNumber(idNumber) {
    const cleanId = String(idNumber).replace(/\D/g, "");

    if (cleanId.length === 18) {
      return `${cleanId.slice(0, 6)} ${cleanId.slice(6, 14)} ${cleanId.slice(
        14
      )}`;
    }

    return cleanId;
  }

  /**
   * 移除所有格式化分隔符
   * @param {string} formattedNumber - 已格式化的数字字符串
   * @returns {string} 纯数字字符串
   *
   * @example
   * removeFormatting('2817 5158 2851 6585') // '2817515828516585'
   */
  static removeFormatting(formattedNumber) {
    return String(formattedNumber).replace(/\D/g, "");
  }
}

export default {
  GeoWatcher,
  NumberFormatter,
};
